package club.yuit.desktop.ui.producer;

import club.yuit.desktop.editor.LogEditorPane;
import club.yuit.desktop.layout.WrapLayout;
import club.yuit.desktop.model.ProducerContext;
import club.yuit.desktop.ui.KeyValuePropertyPanel;
import club.yuit.desktop.ui.UITools;
import club.yuit.rmq.service.ProducerService;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.apis.message.Message;
import org.apache.rocketmq.client.apis.message.MessageId;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.SendReceipt;

import javax.swing.*;
import java.awt.*;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author: yuit
 * @date: 2023/12/12 16:53
 */
@Slf4j
public class ProducerMessageControlPanel extends JPanel {

    private JTextField keys;
    private JButton send;

    private JTextArea body;
    private JTextField tag;
    private JTextField messageGroup;

    private JTextField deliveryTimestamp;
    private JPanel propertiesPanel;

    private ProducerService producerService;


    private ProducerContext context;

    private final AtomicInteger sendCount = new AtomicInteger(0);

    private final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public ProducerMessageControlPanel(ProducerContext context) {
        this.producerService = context.getProducerService();
        this.context = context;
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        propertiesPanel = new JPanel();
        add(keyTagAndTimeDeliveryBox());
        add(propertiesBox());
        add(bodyAndSendButtonBox());

    }

    @Override
    public Insets getInsets() {
        return new Insets(10, 10, 10, 10);
    }


    /**
     * Kyes & Tag and time Box
     */
    private Box keyTagAndTimeDeliveryBox() {
        Box mainBox = Box.createVerticalBox();
        mainBox.add(new Label("Keys&Tag&Message Group&Delivery Timestamp:"));
        Box filedBox = Box.createHorizontalBox();
        keys = new JTextField();
        keys.setMaximumSize(new Dimension(Integer.MAX_VALUE, keys.getPreferredSize().height));
        keys.putClientProperty("JTextField.placeholderText", "多个Key逗号分隔");
        filedBox.add(keys);
        filedBox.add(Box.createHorizontalStrut(10));
        tag = new JTextField();
        tag.setMaximumSize(new Dimension(Integer.MAX_VALUE, tag.getPreferredSize().height));
        tag.putClientProperty("JTextField.placeholderText", "Tag");
        filedBox.add(tag);
        filedBox.add(Box.createHorizontalStrut(10));
        messageGroup = new JTextField();
        messageGroup.setMaximumSize(new Dimension(Integer.MAX_VALUE, messageGroup.getPreferredSize().height));
        messageGroup.putClientProperty("JTextField.placeholderText", "Message Group");
        filedBox.add(messageGroup);
        filedBox.add(Box.createHorizontalStrut(10));
        deliveryTimestamp = new JTextField();
        deliveryTimestamp.setMaximumSize(new Dimension(Integer.MAX_VALUE, deliveryTimestamp.getPreferredSize().height));
        deliveryTimestamp.putClientProperty("JTextField.placeholderText", "Delivery Timestamp(ms)");
        filedBox.add(deliveryTimestamp);
        mainBox.add(filedBox);

        return mainBox;
    }

    /**
     * properties Box
     */
    private Box propertiesBox() {
        Box mainBox = Box.createVerticalBox();


        JPanel controlPanel = new JPanel();
        controlPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
        controlPanel.add(new Label("Properties:"));
        //controlBox.add(Box.createHorizontalStrut(10));
        JButton add = new JButton("+");
        controlPanel.add(add);
        mainBox.add(controlPanel);

        propertiesPanel.setLayout(new WrapLayout(WrapLayout.LEFT, 10, 10));
        add.addActionListener(e -> {
            KeyValuePropertyPanel panel = new KeyValuePropertyPanel(propertiesPanel);
            propertiesPanel.add(panel);
            propertiesPanel.updateUI();
        });

        JScrollPane scrollPane = new JScrollPane(propertiesPanel);
        scrollPane.setPreferredSize(new Dimension(scrollPane.getPreferredSize().width, 100));
        scrollPane.getVerticalScrollBar().setUnitIncrement(15);

        mainBox.add(scrollPane);

        return mainBox;
    }

    /**
     * body and send button Box
     */
    private Box bodyAndSendButtonBox() {
        Box mainBox = Box.createVerticalBox();
        mainBox.add(new Label("Body:"));
        Box filedBox = Box.createHorizontalBox();
        body = new JTextArea();
        body.setRows(3);
        // body.setMaximumSize(new Dimension(Integer.MAX_VALUE,200));
        body.setLineWrap(true);
        JScrollPane sc = new JScrollPane(body);
        filedBox.add(sc);
        send = new JButton("发送");

        //Image scaledInstance = icon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH);
        //ImageIcon newIcon = new ImageIcon(scaledInstance);
        send.setMaximumSize(new Dimension(100, 50));
        send.setIcon(UITools.getSVGIcon("/imgs/send.svg",16,16));
        filedBox.add(Box.createHorizontalStrut(10));
        filedBox.add(send);
        mainBox.add(filedBox);

        send.addActionListener(e -> {
            LogEditorPane logEditorPane = context.getLogEditorPane();
            Message message = createMessage();

            log.debug("send message: \n {}", message);
            Producer producer = context.getProducer();
            String title = String.format("---------(%d)-[%s]----------\n", sendCount.incrementAndGet(), currentTime());
            logEditorPane.insertValue(title, Color.BLACK);
            String s = messageLogString(message);
            logEditorPane.insertValue(s, Color.BLACK);
            send.setEnabled(false);
            CompletableFuture<SendReceipt> future = producer.sendAsync(message);
            future.whenComplete((sendReceipt, throwable) -> {
                if (throwable != null) {
                    logEditorPane.insertValue("[ERROR]\n", Color.RED);
                    logEditorPane.insertValue(throwable.getMessage() + "\n", Color.RED);
                } else {
                    MessageId messageId = sendReceipt.getMessageId();
                    String v = messageId.toString();
                    logEditorPane.insertValue("[SUCCESS]\n", Color.GREEN);
                    logEditorPane.insertValue("MessageId:" + v + "\n", Color.BLACK);
                }
                send.setEnabled(true);
            });
        });
        return mainBox;
    }


    private Message createMessage() {
        String keysText = keys.getText();
        String tagText = tag.getText();
        String bodyText = body.getText();
        String messageGroupText = messageGroup.getText();
        String deliveryTimestampText = deliveryTimestamp.getText();
        Map<String, String> properties = new HashMap<>();
        Component[] components = this.propertiesPanel.getComponents();
        for (Component component : components) {
            if (component instanceof KeyValuePropertyPanel mp) {
                properties.put(mp.getKey(), mp.getValue());
            }
        }

        Long deliveryTimestamp = null;
        if (StringUtils.isNoneBlank(deliveryTimestampText)) {
            deliveryTimestamp = Long.parseLong(deliveryTimestampText);
        }

        return producerService.createMessage(bodyText,
                context.getTopic(), tagText, keysText, messageGroupText, deliveryTimestamp, properties);
    }

    private String messageLogString(Message message) {
        StringBuilder builder = new StringBuilder();
        String keys = String.join(",", message.getKeys());
        builder.append("keys:\n")
                .append(keys);
        if (message.getProperties()!= null) {
            builder.append("\nproperties:\n");
            for (Map.Entry<String, String> entry : message.getProperties().entrySet()) {
                builder.append(entry.getKey()).append("=").append(entry.getValue()).append("\n");
            }
            if (!message.getProperties().isEmpty()){
                builder.deleteCharAt(builder.length() - 1);
            }
        }
        message.getTag().ifPresent(tag -> builder.append("\ntag:\n").append(tag));

        message.getMessageGroup().ifPresent(messageGroup -> builder.append("\nmessageGroup:\n").append(messageGroup));

        message.getDeliveryTimestamp().ifPresent(deliveryTimestamp -> builder.append("\ndeliveryTimestamp:\n").append(deliveryTimestamp));
        ByteBuffer bts = message.getBody();

        byte[] bytes = new byte[bts.remaining()];
        bts.get(bytes);
        String body= new  String(bytes);

        builder.append("\nbody:\n")
                .append(body)
                .append("\n");

        return builder.toString();

    }

    private String currentTime() {
        return LocalDateTime.now().format(format);
    }


}
